home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / sh.sem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  22.3 KB  |  898 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/sh.sem.c,v 3.14 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * sh.sem.c: I/O redirections and job forking. A touchy issue!
  4.  *         Most stuff with builtins is incorrect
  5.  */
  6. /*-
  7.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38. #include "sh.h"
  39.  
  40. RCSID("$Id: sh.sem.c,v 3.14 1991/12/19 22:34:14 christos Exp $")
  41.  
  42. #include "tc.h"
  43.  
  44. #ifdef FIOCLEX
  45. # ifndef SUNOS4
  46. #  ifndef CLEX_DUPS
  47. #   define CLEX_DUPS
  48. #  endif /* CLEX_DUPS */
  49. # endif /* !SUNOS4 */
  50. #endif /* FIOCLEX */
  51.  
  52. #ifdef sparc
  53. # include <vfork.h>
  54. #endif /* sparc */
  55.  
  56. #ifdef VFORK
  57. static    sigret_t    vffree    __P((int));
  58. #endif 
  59. static    Char        *splicepipe    __P((struct command *, Char *));
  60. static    void         doio        __P((struct command *, int *, int *));
  61. static    void         chkclob    __P((char *));
  62.  
  63. /*
  64.  * C shell
  65.  */
  66.  
  67. /*
  68.  * For SVR4, there are problems with pipelines having the first process as
  69.  * the group leader.  The problem occurs when the first process exits before
  70.  * the others have a chance to setpgid().  This is because in SVR4 you can't
  71.  * have a zombie as a group leader.  The solution I have used is to reverse
  72.  * the order in which pipelines are started, making the last process the
  73.  * group leader.  (Note I am not using 'pipeline' in the generic sense -- I
  74.  * mean processes connected by '|'.)  I don't know yet if this causes other
  75.  * problems.
  76.  *
  77.  * All the changes for this are in execute(), and are enclosed in 
  78.  * '#ifdef BACKPIPE'
  79.  *
  80.  * David Dawes (dawes@physics.su.oz.au) Oct 1991
  81.  */
  82.  
  83. /*VARARGS 1*/
  84. void
  85. execute(t, wanttty, pipein, pipeout)
  86.     register struct command *t;
  87.     int     wanttty, *pipein, *pipeout;
  88. {
  89. #if defined(convex) || defined(__convex__)
  90.     extern bool use_fork;    /* use fork() instead of vfork()? */
  91. #endif 
  92.  
  93.     bool    forked = 0;
  94.     struct biltins *bifunc;
  95.     int     pid = 0;
  96.     int     pv[2];
  97.  
  98. #ifdef BSDSIGS
  99.     static sigmask_t csigmask;
  100. # ifdef VFORK
  101.     static sigmask_t ocsigmask;
  102. # endif /* VFORK */
  103. #endif /* BSDSIGS */
  104. #ifdef VFORK
  105.     static int onosigchld = 0;
  106. #endif /* VFORK */
  107.     static int nosigchld = 0;
  108.  
  109.     if (t == 0)
  110.     return;
  111.     /*
  112.      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
  113.      * Don't check for wantty > 0...
  114.      */
  115.     if (t->t_dflg & F_AMPERSAND)
  116.     wanttty = 0;
  117.     switch (t->t_dtyp) {
  118.  
  119.     case NODE_COMMAND:
  120.     if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
  121.         (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
  122.     if ((t->t_dflg & F_REPEAT) == 0)
  123.         Dfix(t);        /* $ " ' \ */
  124.     if (t->t_dcom[0] == 0)
  125.         return;
  126.     /* fall into... */
  127.  
  128.     case NODE_PAREN:
  129. #ifdef BACKPIPE
  130.     if (t->t_dflg & F_PIPEIN)
  131.         mypipe(pipein);
  132. #else /* !BACKPIPE */
  133.     if (t->t_dflg & F_PIPEOUT)
  134.         mypipe(pipeout);
  135. #endif /* BACKPIPE */
  136.     /*
  137.      * Must do << early so parent will know where input pointer should be.
  138.      * If noexec then this is all we do.
  139.      */
  140.     if (t->t_dflg & F_READ) {
  141.         (void) close(0);
  142.         heredoc(t->t_dlef);
  143.         if (noexec)
  144.         (void) close(0);
  145.     }
  146.  
  147.     set(STRstatus, Strsave(STR0));
  148.  
  149.     /*
  150.      * This mess is the necessary kludge to handle the prefix builtins:
  151.      * nice, nohup, time.  These commands can also be used by themselves,
  152.      * and this is not handled here. This will also work when loops are
  153.      * parsed.
  154.      */
  155.     while (t->t_dtyp == NODE_COMMAND)
  156.         if (eq(t->t_dcom[0], STRnice))
  157.         if (t->t_dcom[1])
  158.             if (strchr("+-", t->t_dcom[1][0]))
  159.             if (t->t_dcom[2]) {
  160.                 setname("nice");
  161.                 t->t_nice =
  162.                 getn(t->t_dcom[1]);
  163.                 lshift(t->t_dcom, 2);
  164.                 t->t_dflg |= F_NICE;
  165.             }
  166.             else
  167.                 break;
  168.             else {
  169.             t->t_nice = 4;
  170.             lshift(t->t_dcom, 1);
  171.             t->t_dflg |= F_NICE;
  172.             }
  173.         else
  174.             break;
  175.         else if (eq(t->t_dcom[0], STRnohup))
  176.         if (t->t_dcom[1]) {
  177.             t->t_dflg |= F_NOHUP;
  178.             lshift(t->t_dcom, 1);
  179.         }
  180.         else
  181.             break;
  182.         else if (eq(t->t_dcom[0], STRtime))
  183.         if (t->t_dcom[1]) {
  184.             t->t_dflg |= F_TIME;
  185.             lshift(t->t_dcom, 1);
  186.         }
  187.         else
  188.             break;
  189. #ifdef F_VER
  190.         else if (eq(t->t_dcom[0], STRver))
  191.         if (t->t_dcom[1] && t->t_dcom[2]) {
  192.             setname("ver");
  193.             t->t_systype = getv(t->t_dcom[1]);
  194.             lshift(t->t_dcom, 2);
  195.             t->t_dflg |= F_VER;
  196.         }
  197.         else
  198.             break;
  199. #endif  /* F_VER */
  200.         else
  201.         break;
  202.  
  203.     /* is it a command */
  204.     if (t->t_dtyp == NODE_COMMAND) {
  205.         /*
  206.          * Check if we have a builtin function and remember which one.
  207.          */
  208.         bifunc = isbfunc(t);
  209.          if (noexec) {
  210.         /*
  211.          * Continue for builtins that are part of the scripting language
  212.          */
  213.         if (bifunc->bfunct != (void (*)())dobreak    &&
  214.             bifunc->bfunct != (void (*)())docontin    &&
  215.             bifunc->bfunct != (void (*)())doelse    &&
  216.             bifunc->bfunct != (void (*)())doend    &&
  217.             bifunc->bfunct != (void (*)())doforeach    &&
  218.             bifunc->bfunct != (void (*)())dogoto    &&
  219.             bifunc->bfunct != (void (*)())doif    &&
  220.             bifunc->bfunct != (void (*)())dorepeat    &&
  221.             bifunc->bfunct != (void (*)())doswbrk    &&
  222.             bifunc->bfunct != (void (*)())doswitch    &&
  223.             bifunc->bfunct != (void (*)())dowhile    &&
  224.             bifunc->bfunct != (void (*)())dozip)
  225.             break;
  226.         }
  227.     }
  228.     else {            /* not a command */
  229.         bifunc = NULL;
  230.         if (noexec)
  231.         break;
  232.     }
  233.  
  234.     /*
  235.      * We fork only if we are timed, or are not the end of a parenthesized
  236.      * list and not a simple builtin function. Simple meaning one that is
  237.      * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
  238.      * fork in some of these cases.
  239.      */
  240.     /*
  241.      * Prevent forking cd, pushd, popd, chdir cause this will cause the
  242.      * shell not to change dir!
  243.      */
  244. #ifdef BACKPIPE
  245.     /*
  246.      * Can't have NOFORK for the tail of a pipe - because it is not the
  247.      * last command spawned (even if it is at the end of a parenthesised
  248.      * list).
  249.      */
  250.     if (t->t_dflg & F_PIPEIN)
  251.         t->t_dflg &= ~(F_NOFORK);
  252. #endif /* BACKPIPE */
  253.     if (bifunc && (bifunc->bfunct == (void(*)())dochngd ||
  254.                bifunc->bfunct == (void(*)())dopushd ||
  255.                bifunc->bfunct == (void(*)())dopopd))
  256.         t->t_dflg &= ~(F_NICE);
  257.     if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
  258.          (!bifunc || t->t_dflg &
  259.           (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) ||
  260.     /*
  261.      * We have to fork for eval too.
  262.      */
  263.         (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
  264.          bifunc->bfunct == (void(*)())doeval))
  265. #ifdef VFORK
  266.         if (t->t_dtyp == NODE_PAREN ||
  267.         t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc)
  268. #endif /* VFORK */
  269.         {
  270.         forked++;
  271.         /*
  272.          * We need to block SIGCHLD here, so that if the process does
  273.          * not die before we can set the process group
  274.          */
  275.         if (wanttty >= 0 && !nosigchld) {
  276. #ifdef BSDSIGS
  277.             csigmask = sigblock(sigmask(SIGCHLD));
  278. #else /* !BSDSIGS */
  279.             sighold(SIGCHLD);
  280. #endif /* BSDSIGS */
  281.  
  282.             nosigchld = 1;
  283.         }
  284.  
  285.         pid = pfork(t, wanttty);
  286.         if (pid == 0 && nosigchld) {
  287. #ifdef BSDSIGS
  288.             (void) sigsetmask(csigmask);
  289. #else /* !BSDSIGS */
  290.             (void) sigrelse(SIGCHLD);
  291. #endif /* BSDSIGS */
  292.             nosigchld = 0;
  293.         }
  294.         else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
  295.             backpid = pid;
  296.         }
  297.  
  298. #ifdef VFORK
  299.         else {
  300.         int     ochild, osetintr, ohaderr, odidfds;
  301.         int     oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
  302.         int     oisoutatty, oisdiagatty;
  303.  
  304. # ifndef FIOCLEX
  305.         int     odidcch;
  306.  
  307. # endif  /* !FIOCLEX */
  308. # ifdef BSDSIGS
  309.         sigmask_t omask;
  310. # endif /* BSDSIGS */
  311.  
  312.         /*
  313.          * Prepare for the vfork by saving everything that the child
  314.          * corrupts before it exec's. Note that in some signal
  315.          * implementations which keep the signal info in user space
  316.          * (e.g. Sun's) it will also be necessary to save and restore
  317.          * the current sigvec's for the signals the child touches
  318.          * before it exec's.
  319.          */
  320. # ifdef BSDSIGS
  321.  
  322.         /*
  323.          * Sooooo true... If this is a Sun, save the sigvec's. (Skip
  324.          * Gilbrech - 11/22/87)
  325.          */
  326. #  ifdef SAVESIGVEC
  327.         sigvec_t savesv[NSIGSAVED];
  328.         sigmask_t savesm;
  329.  
  330. #  endif /* SAVESIGVEC */
  331.         if (wanttty >= 0 && !nosigchld && !noexec) {
  332.             csigmask = sigblock(sigmask(SIGCHLD));
  333.             nosigchld = 1;
  334.         }
  335.         omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT));
  336. # else /* !BSDSIGS */
  337.         (void) sighold(SIGCHLD);
  338.         (void) sighold(SIGINT);
  339. # endif  /* !BSDSIGS */
  340.         ochild = child;
  341.         osetintr = setintr;
  342.         ohaderr = haderr;
  343.         odidfds = didfds;
  344. # ifndef FIOCLEX
  345.         odidcch = didcch;
  346. # endif /* !FIOCLEX */
  347.         oSHIN = SHIN;
  348.         oSHOUT = SHOUT;
  349.         oSHDIAG = SHDIAG;
  350.         oOLDSTD = OLDSTD;
  351.         otpgrp = tpgrp;
  352.         oisoutatty = isoutatty;
  353.         oisdiagatty = isdiagatty;
  354. # ifdef BSDSIGS
  355.         ocsigmask = csigmask;
  356. # endif /* BSDSIGS */
  357.         onosigchld = nosigchld;
  358.         Vsav = Vdp = 0;
  359.         Vexpath = 0;
  360.         Vt = 0;
  361. # ifdef SAVESIGVEC
  362.         savesm = savesigvec(savesv);
  363. # endif /* SAVESIGVEC */
  364. # if defined(convex) || defined(__convex__)
  365.         if (use_fork)
  366.             pid = fork();
  367.         else
  368.             pid = vfork();
  369. # else /* !convex && !__convex__ */
  370.         pid = vfork();
  371. # endif /* convex || __CONVEX__ */
  372.  
  373.         if (pid < 0) {
  374. # ifdef BSDSIGS
  375. #  ifdef SAVESIGVEC
  376.             restoresigvec(savesv, savesm);
  377. #  endif /* SAVESIGVEC */
  378.             (void) sigsetmask(omask);
  379. # else /* !BSDSIGS */
  380.             (void) sigrelse(SIGCHLD);
  381.             (void) sigrelse(SIGINT);
  382. #endif  /* BSDSIGS */
  383.             stderror(ERR_NOPROC);
  384.         }
  385.         forked++;
  386.         if (pid) {    /* parent */
  387. # ifdef BSDSIGS
  388. #  ifdef SAVESIGVEC
  389.             restoresigvec(savesv, savesm);
  390. #  endif /* SAVESIGVEC */
  391. # endif /* BSDSIGS */
  392.             child = ochild;
  393.             setintr = osetintr;
  394.             haderr = ohaderr;
  395.             didfds = odidfds;
  396.             SHIN = oSHIN;
  397. # ifndef FIOCLEX
  398.             didcch = odidcch;
  399. # endif /* !FIOCLEX */
  400.             SHOUT = oSHOUT;
  401.             SHDIAG = oSHDIAG;
  402.             OLDSTD = oOLDSTD;
  403.             tpgrp = otpgrp;
  404.             isoutatty = oisoutatty;
  405.             isdiagatty = oisdiagatty;
  406. # ifdef BSDSIGS
  407.             csigmask = ocsigmask;
  408. # endif /* BSDSIGS */
  409.             nosigchld = onosigchld;
  410.  
  411.             xfree((ptr_t) Vsav);
  412.             Vsav = 0;
  413.             xfree((ptr_t) Vdp);
  414.             Vdp = 0;
  415.             xfree((ptr_t) Vexpath);
  416.             Vexpath = 0;
  417.             blkfree((Char **) Vt);
  418.             Vt = 0;
  419.             /* this is from pfork() */
  420.             palloc(pid, t);
  421. # ifdef BSDSIGS
  422.             (void) sigsetmask(omask);
  423. # else /* !BSDSIGS */
  424.             (void) sigrelse(SIGCHLD);
  425.             (void) sigrelse(SIGINT);
  426. # endif  /* BSDSIGS */
  427.         }
  428.         else {        /* child */
  429.             /* this is from pfork() */
  430.             int     pgrp;
  431.             bool    ignint = 0;
  432.  
  433.             if (nosigchld) {
  434. # ifdef BSDSIGS
  435.             (void) sigsetmask(csigmask);
  436. # else /* !BSDSIGS */
  437.             (void) sigrelse(SIGCHLD);
  438. # endif /* BSDSIGS */
  439.             nosigchld = 0;
  440.             }
  441.  
  442.             if (setintr)
  443.             ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
  444.                 || (gointr && eq(gointr, STRminus));
  445.             pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
  446.             child++;
  447.             if (setintr) {
  448.             setintr = 0;
  449. # ifdef notdef
  450.             (void) signal(SIGCHLD, SIG_DFL);
  451. # endif 
  452. /*
  453.  * casts made right for SunOS 4.0 by Douglas C. Schmidt
  454.  * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU>
  455.  * (thanks! -- PWP)
  456.  *
  457.  * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET>
  458.  * (thanks again)
  459.  */
  460.             if (ignint) {
  461.                 (void) signal(SIGINT, SIG_IGN);
  462.                 (void) signal(SIGQUIT, SIG_IGN);
  463.             }
  464.             else {
  465.                 (void) signal(SIGINT,  vffree);
  466.                 (void) signal(SIGQUIT, SIG_DFL);
  467.             }
  468. # ifdef BSDJOBS
  469.             if (wanttty >= 0) {
  470.                 (void) signal(SIGTSTP, SIG_DFL);
  471.                 (void) signal(SIGTTIN, SIG_DFL);
  472.                 (void) signal(SIGTTOU, SIG_DFL);
  473.             }
  474. # endif /* BSDJOBS */
  475.  
  476.             (void) signal(SIGTERM, parterm);
  477.             }
  478.             else if (tpgrp == -1 &&
  479.                  (t->t_dflg & F_NOINTERRUPT)) {
  480.             (void) signal(SIGINT, SIG_IGN);
  481.             (void) signal(SIGQUIT, SIG_IGN);
  482.             }
  483.  
  484. # ifdef _SEQUENT_
  485.             /*
  486.              * On some machines (POSIX) the process group leader
  487.              * cannot be a zombie. On those machines, the following
  488.              * might help. Note that BACKPIPE will break if the
  489.              * last process exits too soon.
  490.              * (From Jaap)
  491.              */
  492.             pgetty(wanttty ? wanttty : 1, pgrp);
  493. # else /* _SEQUENT_ */
  494.             pgetty(wanttty, pgrp);
  495. # endif /* _SEQUENT_ */
  496.  
  497.             if (t->t_dflg & F_NOHUP)
  498.             (void) signal(SIGHUP, SIG_IGN);
  499.             if (t->t_dflg & F_NICE)
  500. # ifdef BSDNICE
  501.             (void) setpriority(PRIO_PROCESS,
  502.                        0, t->t_nice);
  503. # else /* !BSDNICE */
  504.             (void) nice(t->t_nice);
  505. # endif /* BSDNICE */
  506. # ifdef F_VER
  507.             if (t->t_dflg & F_VER) {
  508.             Setenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
  509.             dohash(NULL, NULL);
  510.             }
  511. # endif /* F_VER */
  512.         }
  513.  
  514.         }
  515. #endif /* VFORK */
  516.     if (pid != 0) {
  517.         /*
  518.          * It would be better if we could wait for the whole job when we
  519.          * knew the last process had been started.  Pwait, in fact, does
  520.          * wait for the whole job anyway, but this test doesn't really
  521.          * express our intentions.
  522.          */
  523. #ifdef BACKPIPE
  524.         if (didfds == 0 && t->t_dflg & F_PIPEOUT) {
  525.         (void) close(pipeout[0]);
  526.         (void) close(pipeout[1]);
  527.         }
  528.         if ((t->t_dflg & F_PIPEIN) != 0)
  529.         break;
  530. #else /* !BACKPIPE */
  531.         if (didfds == 0 && t->t_dflg & F_PIPEIN) {
  532.         (void) close(pipein[0]);
  533.         (void) close(pipein[1]);
  534.         }
  535.         if ((t->t_dflg & F_PIPEOUT) != 0)
  536.         break;
  537. #endif /* BACKPIPE */
  538.  
  539.         if (nosigchld) {
  540. #ifdef BSDSIGS
  541.         (void) sigsetmask(csigmask);
  542. #else /* !BSDSIGS */
  543.         (void) sigrelse(SIGCHLD);
  544. #endif /* BSDSIGS */
  545.         nosigchld = 0;
  546.         }
  547.         if ((t->t_dflg & F_AMPERSAND) == 0)
  548.         pwait();
  549.         break;
  550.     }
  551.  
  552.     doio(t, pipein, pipeout);
  553. #ifdef BACKPIPE
  554.     if (t->t_dflg & F_PIPEIN) {
  555.         (void) close(pipein[0]);
  556.         (void) close(pipein[1]);
  557.     }
  558. #else /* !BACKPIPE */
  559.     if (t->t_dflg & F_PIPEOUT) {
  560.         (void) close(pipeout[0]);
  561.         (void) close(pipeout[1]);
  562.     }
  563. #endif /* BACKPIPE */
  564.     /*
  565.      * Perform a builtin function. If we are not forked, arrange for
  566.      * possible stopping
  567.      */
  568.     if (bifunc) {
  569.         func(t, bifunc);
  570.         if (forked)
  571.         exitstat();
  572.         break;
  573.     }
  574.     if (t->t_dtyp != NODE_PAREN) {
  575.         doexec(t);
  576.         /* NOTREACHED */
  577.     }
  578.     /*
  579.      * For () commands must put new 0,1,2 in FSH* and recurse
  580.      */
  581.     OLDSTD = dcopy(0, FOLDSTD);
  582.     SHOUT = dcopy(1, FSHOUT);
  583.     isoutatty = isatty(SHOUT);
  584.     SHDIAG = dcopy(2, FSHDIAG);
  585.     isdiagatty = isatty(SHDIAG);
  586.     (void) close(SHIN);
  587.     SHIN = -1;
  588. #ifndef FIOCLEX
  589.     didcch = 0;
  590. #endif /* !FIOCLEX */
  591.     didfds = 0;
  592.     wanttty = -1;
  593.     t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
  594.     execute(t->t_dspr, wanttty, NULL, NULL);
  595.     exitstat();
  596.  
  597.     case NODE_PIPE:
  598. #ifdef BACKPIPE
  599.     t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
  600.             (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
  601.     execute(t->t_dcdr, wanttty, pv, pipeout);
  602.     t->t_dcar->t_dflg |= F_PIPEOUT |
  603.         (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
  604.     if (wanttty > 0)
  605.         wanttty = 0;    /* got tty already */
  606.     execute(t->t_dcar, wanttty, pipein, pv);
  607. #else /* !BACKPIPE */
  608.     t->t_dcar->t_dflg |= F_PIPEOUT |
  609.         (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
  610.     execute(t->t_dcar, wanttty, pipein, pv);
  611.     t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
  612.             (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
  613.     if (wanttty > 0)
  614.         wanttty = 0;    /* got tty already */
  615.     execute(t->t_dcdr, wanttty, pv, pipeout);
  616. #endif /* BACKPIPE */
  617.     break;
  618.  
  619.     case NODE_LIST:
  620.     if (t->t_dcar) {
  621.         t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
  622.         execute(t->t_dcar, wanttty, NULL, NULL);
  623.         /*
  624.          * In strange case of A&B make a new job after A
  625.          */
  626.         if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
  627.         (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
  628.         pendjob();
  629.     }
  630.     if (t->t_dcdr) {
  631.         t->t_dcdr->t_dflg |= t->t_dflg &
  632.         (F_NOFORK | F_NOINTERRUPT);
  633.         execute(t->t_dcdr, wanttty, NULL, NULL);
  634.     }
  635.     break;
  636.  
  637.     case NODE_OR:
  638.     case NODE_AND:
  639.     if (t->t_dcar) {
  640.         t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
  641.         execute(t->t_dcar, wanttty, NULL, NULL);
  642.         if ((getn(value(STRstatus)) == 0) !=
  643.         (t->t_dtyp == NODE_AND))
  644.         return;
  645.     }
  646.     if (t->t_dcdr) {
  647.         t->t_dcdr->t_dflg |= t->t_dflg &
  648.         (F_NOFORK | F_NOINTERRUPT);
  649.         execute(t->t_dcdr, wanttty, NULL, NULL);
  650.     }
  651.     break;
  652.  
  653.     default:
  654.     break;
  655.     }
  656.     /*
  657.      * Fall through for all breaks from switch
  658.      * 
  659.      * If there will be no more executions of this command, flush all file
  660.      * descriptors. Places that turn on the F_REPEAT bit are responsible for
  661.      * doing donefds after the last re-execution
  662.      */
  663.     if (didfds && !(t->t_dflg & F_REPEAT))
  664.     donefds();
  665. }
  666.  
  667. #ifdef VFORK
  668. static sigret_t
  669. /*ARGSUSED*/
  670. vffree(snum)
  671. int snum;
  672. {
  673.     register Char **v;
  674.  
  675.     if (v = gargv) {
  676.     gargv = 0;
  677.     xfree((ptr_t) v);
  678.     }
  679.     if (v = pargv) {
  680.     pargv = 0;
  681.     xfree((ptr_t) v);
  682.     }
  683.     _exit(1);
  684. #ifndef SIGVOID
  685.     /*NOTREACHED*/
  686.     return(0);
  687. #endif /* SIGVOID */
  688. }
  689. #endif /* VFORK */
  690.  
  691. /*
  692.  * Expand and glob the words after an i/o redirection.
  693.  * If more than one word is generated, then update the command vector.
  694.  *
  695.  * This is done differently in all the shells:
  696.  * 1. in the bourne shell and ksh globbing is not performed
  697.  * 2. Bash/csh say ambiguous
  698.  * 3. zsh does i/o to/from all the files
  699.  * 4. itcsh concatenates the words.
  700.  *
  701.  * I don't know what is best to do. I think that Ambiguous is better
  702.  * than restructuring the command vector, because the user can get
  703.  * unexpected results. In any case, the command vector restructuring 
  704.  * code is present and the user can choose it by setting noambiguous
  705.  */
  706. static Char *
  707. splicepipe(t, cp)
  708.     register struct command *t;
  709.     Char *cp;    /* word after < or > */
  710. {
  711.     Char *blk[2];
  712.  
  713.     if (adrof(STRnoambiguous)) {
  714.     Char **pv;
  715.  
  716.     blk[0] = Dfix1(cp); /* expand $ */
  717.     blk[1] = NULL;
  718.  
  719.     gflag = 0, tglob(blk);
  720.     if (gflag) {
  721.         pv = globall(blk);
  722.         if (pv == NULL) {
  723.         setname(short2str(blk[0]));
  724.         xfree((ptr_t) blk[0]);
  725.         stderror(ERR_NAME | ERR_NOMATCH);
  726.         }
  727.         gargv = NULL;
  728.         if (pv[1] != NULL) { /* we need to fix the command vector */
  729.         Char **av = blkspl(t->t_dcom, &pv[1]);
  730.         xfree((ptr_t) t->t_dcom);
  731.         t->t_dcom = av;
  732.         }
  733.         xfree((ptr_t) blk[0]);
  734.         blk[0] = pv[0];
  735.         xfree((ptr_t) pv);
  736.     }
  737.     }
  738.     else {
  739.     Char buf[BUFSIZE];
  740.  
  741.     (void) Strcpy(buf, blk[1] = Dfix1(cp));
  742.     xfree((ptr_t) blk[1]);
  743.     blk[0] = globone(buf, G_ERROR);
  744.     }
  745.     return(blk[0]);
  746. }
  747.     
  748. /*
  749.  * Perform io redirection.
  750.  * We may or maynot be forked here.
  751.  */
  752. static void
  753. doio(t, pipein, pipeout)
  754.     register struct command *t;
  755.     int    *pipein, *pipeout;
  756. {
  757.     register int fd;
  758.     register Char *cp;
  759.     register int flags = t->t_dflg;
  760.  
  761.     if (didfds || (flags & F_REPEAT))
  762.     return;
  763.     if ((flags & F_READ) == 0) {/* F_READ already done */
  764.     if (t->t_dlef) {
  765.         char    tmp[MAXPATHLEN+1];
  766.  
  767.         /*
  768.          * so < /dev/std{in,out,err} work
  769.          */
  770.         (void) dcopy(SHIN, 0);
  771.         (void) dcopy(SHOUT, 1);
  772.         (void) dcopy(SHDIAG, 2);
  773.         cp = splicepipe(t, t->t_dlef);
  774.         (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
  775.         tmp[MAXPATHLEN] = '\0';
  776.         xfree((ptr_t) cp);
  777.         if ((fd = open(tmp, O_RDONLY)) < 0)
  778.         stderror(ERR_SYSTEM, tmp, strerror(errno));
  779.         (void) dmove(fd, 0);
  780.     }
  781.     else if (flags & F_PIPEIN) {
  782.         (void) close(0);
  783.         (void) dup(pipein[0]);
  784.         (void) close(pipein[0]);
  785.         (void) close(pipein[1]);
  786.     }
  787.     else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
  788.         (void) close(0);
  789.         (void) open(_PATH_DEVNULL, O_RDONLY);
  790.     }
  791.     else {
  792.         (void) close(0);
  793.         (void) dup(OLDSTD);
  794. #ifdef FIOCLEX
  795. # ifdef CLEX_DUPS
  796.         /*
  797.          * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved
  798.          * across dup()s, so we have to UNSET it here or else we get a
  799.          * command with NO stdin, stdout, or stderr at all (a bad thing
  800.          * indeed)
  801.          */
  802.         (void) ioctl(0, FIONCLEX, NULL);
  803. # endif /* CLEX_DUPS */
  804. #endif /* FIONCLEX */
  805.     }
  806.     }
  807.     if (t->t_drit) {
  808.     char    tmp[MAXPATHLEN+1];
  809.  
  810.     cp = splicepipe(t, t->t_drit);
  811.     (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
  812.     tmp[MAXPATHLEN] = '\0';
  813.     xfree((ptr_t) cp);
  814.     /*
  815.      * so > /dev/std{out,err} work
  816.      */
  817.     (void) dcopy(SHOUT, 1);
  818.     (void) dcopy(SHDIAG, 2);
  819.     if ((flags & F_APPEND) &&
  820. #ifdef O_APPEND
  821.         (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
  822. #else /* !O_APPEND */
  823.         (fd = open(tmp, O_WRONLY)) >= 0)
  824.         (void) lseek(1, (off_t) 0, L_XTND);
  825. #endif /* O_APPEND */
  826.     else {
  827.         if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
  828.         if (flags & F_APPEND)
  829.             stderror(ERR_SYSTEM, tmp, strerror(errno));
  830.         chkclob(tmp);
  831.         }
  832.         if ((fd = creat(tmp, 0666)) < 0)
  833.         stderror(ERR_SYSTEM, tmp, strerror(errno));
  834.     }
  835.     (void) dmove(fd, 1);
  836.     is1atty = isatty(1);
  837.     }
  838.     else if (flags & F_PIPEOUT) {
  839.     (void) close(1);
  840.     (void) dup(pipeout[1]);
  841.     is1atty = 0;
  842.     }
  843.     else {
  844.     (void) close(1);
  845.     (void) dup(SHOUT);
  846.     is1atty = isoutatty;
  847. #ifdef FIOCLEX
  848. # ifdef CLEX_DUPS
  849.     (void) ioctl(1, FIONCLEX, NULL);
  850. # endif /* CLEX_DUPS */
  851. #endif /* FIONCLEX */
  852.     }
  853.  
  854.     (void) close(2);
  855.     if (flags & F_STDERR) {
  856.     (void) dup(1);
  857.     is2atty = is1atty;
  858.     }
  859.     else {
  860.     (void) dup(SHDIAG);
  861.     is2atty = isdiagatty;
  862. #ifdef FIOCLEX
  863. # ifdef CLEX_DUPS
  864.     (void) ioctl(2, FIONCLEX, NULL);
  865. # endif /* CLEX_DUPS */
  866. #endif /* FIONCLEX */
  867.     }
  868.     didfds = 1;
  869. }
  870.  
  871. void
  872. mypipe(pv)
  873.     register int *pv;
  874. {
  875.  
  876.     if (pipe(pv) < 0)
  877.     goto oops;
  878.     pv[0] = dmove(pv[0], -1);
  879.     pv[1] = dmove(pv[1], -1);
  880.     if (pv[0] >= 0 && pv[1] >= 0)
  881.     return;
  882. oops:
  883.     stderror(ERR_PIPE);
  884. }
  885.  
  886. static void
  887. chkclob(cp)
  888.     register char *cp;
  889. {
  890.     struct stat stb;
  891.  
  892.     if (stat(cp, &stb) < 0)
  893.     return;
  894.     if (S_ISCHR(stb.st_mode))
  895.     return;
  896.     stderror(ERR_EXISTS, cp);
  897. }
  898.